package es.ugr.beequizz.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import es.ugr.beequizz.bean.InformacionUsuarioBean;
import es.ugr.beequizz.bean.PuntuacionBean;
import es.ugr.beequizz.dto.EnunciadoDTO;
import es.ugr.beequizz.dto.EnunciadoRespuestaDTO;
import es.ugr.beequizz.dto.IdDTO;
import es.ugr.beequizz.dto.PartidaConDificultadYTemaDTO;
import es.ugr.beequizz.dto.PartidaDTO;
import es.ugr.beequizz.dto.PartidaMultijugadorDTO;
import es.ugr.beequizz.dto.PuntosDTO;
import es.ugr.beequizz.dto.PuntuacionDTO;
import es.ugr.beequizz.dto.RespuestaPreguntaDTO;
import es.ugr.beequizz.dto.ResultadoDTO;
import es.ugr.beequizz.dto.TurnoDTO;
import es.ugr.beequizz.dto.ValidarRespuestaDTO;
import es.ugr.beequizz.model.Juego;
import es.ugr.beequizz.model.Pregunta;
import es.ugr.beequizz.model.Respuesta;
import es.ugr.beequizz.services.JuegoService;
import es.ugr.beequizz.services.MailService;
import es.ugr.beequizz.services.PartidaService;
import es.ugr.beequizz.services.PreguntaService;
import es.ugr.beequizz.services.RespuestaService;
import es.ugr.beequizz.services.UsuarioService;

@Controller
@RequestMapping(value= "/juego")
public class JuegoController {


	@Autowired
	private PreguntaService preguntaService;
	
	@Autowired
	private PartidaService partidaService;
	
	@Autowired
	private UsuarioService usuarioService;
	
	@Autowired
	private MailService mailService;
	
	@Autowired
	private JuegoService juegoService;
	
	@Autowired
	private RespuestaService respuestaService;
	
	
/*M�todo mediante el cual voy a recuperar una lista de preguntas especificando
 * el numero de preguntas deseados, la asignatura y el nivel */
	
	@RequestMapping(value= "/recuperarListaPreguntas",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"numPreguntas","asignaturaId", "dificultadId"})
	@ResponseBody
	public List<IdDTO> recuperarListaPreguntas ( @RequestParam(value = "numPreguntas") int numPreguntas, @RequestParam(value = "asignaturaId") Long asignaturaId,
			@RequestParam(value = "dificultadId") Long dificultadId){
	
	List<Pregunta> preguntasBean = preguntaService.recuperarListaPreguntas(numPreguntas, asignaturaId, dificultadId);
	List<IdDTO> ids = new ArrayList<IdDTO>();
	
	for (Pregunta pregunta : preguntasBean) {
		
		IdDTO dto = new IdDTO();
		dto.setId(pregunta.getId());
		
		ids.add(dto);
	}

	return ids;
	}
	
	/*Metodo para recuperar el contenido de una pregunta pasandole como argumento una id*/
	@RequestMapping(value= "/recuperarContenidoPreguntas",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"preguntaId"})
	@ResponseBody
	public EnunciadoDTO recuperarContenidoPreguntas(@RequestParam(value = "preguntaId") Long preguntaId){
		
		Pregunta preguntasBean = preguntaService.recuperarContenidoPreguntas(preguntaId);
		
		EnunciadoDTO enunciado = new EnunciadoDTO();
		
		enunciado.setEnunciado(preguntasBean.getEnunciado());
		enunciado.setPuntuacion(preguntasBean.getPuntuacion());
		
		
		return enunciado;
	}
	
	/*Metodo para recuperar un numero determinado de respuestas asociadas a una pregunta*/
	
	@RequestMapping(value= "/recuperarContenidoRespuestas",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"numRespuestasOK", "numRespuestasKO", "preguntaId"})
	@ResponseBody
	public List<EnunciadoRespuestaDTO> recuperarContenidoRespuestas(@RequestParam(value="numRespuestasOK") int numRespuestasOK, 
				@RequestParam(value="numRespuestasKO") int numRespuestasKO, @RequestParam(value="preguntaId") Long preguntaId){
		
		List<Respuesta> respuestasBean = respuestaService.recuperarContenidoRespuestas(numRespuestasOK, numRespuestasKO, preguntaId);
		List<EnunciadoRespuestaDTO> enunciadoRespuesta = new ArrayList<EnunciadoRespuestaDTO>(); 
		
		for(Respuesta respuesta : respuestasBean){
			EnunciadoRespuestaDTO dto = new EnunciadoRespuestaDTO();
			dto.setId(respuesta.getId());
			dto.setEnunciado(respuesta.getContenidoRespuesta());
			
			enunciadoRespuesta.add(dto);
			
		}
		return enunciadoRespuesta;
	}
	
	
	/*M�todo para verificar que la respuesta es correcta*/
	@RequestMapping(value= "/validarRespuesta", method= RequestMethod.GET, 
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"respuestaId"})
	@ResponseBody
	public ValidarRespuestaDTO validarRespuesta(@RequestParam(value="respuestaId") Long respuestaId){
		
		boolean correcta = respuestaService.validarRespuesta(respuestaId);
		ValidarRespuestaDTO validarRespuesta = new ValidarRespuestaDTO();
		
		validarRespuesta.setRespuestaCorrecta(correcta);
		
		return validarRespuesta;
	}
	
	/*M�todo para dar la puntuacion a cada usuario*/
	@RequestMapping(value="/resultado", method= RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public ResultadoDTO resultadoPartida(@RequestBody PuntosDTO puntos){
		
		partidaService.resultadoPartida(puntos.getPartidaId(), puntos.getUsuarioId(), puntos.getPuntuacionTotal());
		partidaService.puntuacion(puntos.getPartidaId(), puntos.getUsuarioId(), puntos.getPuntuacionTotal());
		
		return new ResultadoDTO("SUCCESS");
	}
	
	/*M�todo para crear una partida*/
	@RequestMapping(value="/crearPartida", method = RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Long crearPartida(@RequestBody  PartidaConDificultadYTemaDTO partida){
		 Long idPartida = partidaService.crearPartida(partida.getJugadorId(),partida.getJuegoId(), partida.getTema(), partida.getDificultad());
		 partidaService.registrarJugador(idPartida, partida.getJugadorId());
		return idPartida;
	}
	
	/*M�todo para crear una partida*/
	@RequestMapping(value="/crearPartidaConDificultadYTema", method = RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Long crearPartidaConDificultadYTema(@RequestBody  PartidaConDificultadYTemaDTO partida){
		Long idPartida = partidaService.crearPartida(partida.getJugadorId(), partida.getJuegoId(), partida.getTema(), partida.getDificultad());
		 
		return idPartida;
	}
	
	/*Partida multijugadores: Asigna la partida creada al resto de los jugadores*/
	
	@RequestMapping(value="/partidaMultijugador", method = RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public ResultadoDTO partidaMultijugador(@RequestBody PartidaMultijugadorDTO partidaMultijugador){
				
		partidaService.partidaMultijugador(partidaMultijugador.getIdPartida(),partidaMultijugador.getIdJugador());
		 
		return new ResultadoDTO("SUCCESS");
	}
	
	@RequestMapping(value= "/notificacionJuego",method= RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	
	public ResultadoDTO notificacionJuego(@RequestBody PartidaMultijugadorDTO partidaMultijugador){
		
	
		
		final String usernamePrincipal = SecurityContextHolder.getContext().getAuthentication().getName();
		
		/*recuperar la id del juego a partir de la id de la partida*/
		Juego juego = juegoService.recuperarJuegoPartida(partidaMultijugador.getIdPartida());
		
		String nombreJuego= juego.getNombre();
		
		
		/*Servicio para recuperar el username (apodo) y el mail de todas las ids de la lista */
		List<InformacionUsuarioBean> informacion = usuarioService.informacionUsuario(partidaMultijugador.getIdJugador());
		
		/*Envio el mail a todos los usuarios de la lista*/
		for(InformacionUsuarioBean usuario : informacion){
			String mail = usuario.getMail();
			mailService.notificacion(usernamePrincipal, mail, nombreJuego);
		}
		
		
		return new ResultadoDTO("SUCCESS");
	}
	
	/*PreguntasPartida: Relaciona una serie de preguntas con una partida*/
	@RequestMapping(value= "/preguntasPartida",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"numPreguntas","asignaturaId", "dificultadId", "partidaId"})
	@ResponseBody
	public List<IdDTO> preguntasPartida ( @RequestParam(value = "numPreguntas") int numPreguntas, @RequestParam(value = "asignaturaId") Long asignaturaId,
			@RequestParam(value = "dificultadId") Long dificultadId, @RequestParam(value = "partidaId") Long partidaId){

		List<Pregunta> preguntasBean = preguntaService.recuperarListaPreguntas(numPreguntas, asignaturaId, dificultadId);
		List<IdDTO> ids = new ArrayList<IdDTO>();

		for (Pregunta pregunta : preguntasBean) {

			IdDTO dto = new IdDTO();
			dto.setId(pregunta.getId());

			ids.add(dto);
		}

		/*Servicio para completar la tabla preguntas_partidas*/
		partidaService.preguntasPartida(partidaId, preguntasBean);

		return ids;
	}
	

	/*Recuperar la lista de ids pasando como argumento la id de la partida*/
	@RequestMapping(value= "/recuperarListaPreguntasPartida",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"partidaId"})
	@ResponseBody
	public List<IdDTO> recuperarListaPreguntas ( @RequestParam(value = "partidaId") Long partidaId){

		List<Long> ids = preguntaService.recuperarListaPreguntasPartida(partidaId);

		List<IdDTO> idsDTO = new ArrayList<IdDTO>();

		for (Long id : ids) {

			IdDTO dto = new IdDTO();
			dto.setId(id);

			idsDTO.add(dto);
		}
		return idsDTO;
	}
	
	/*GuardarRespuestaPregunta: Guardamos la respuesta que el usuario da para una de las preguntas propuestas*/
	@RequestMapping(value= "/guardarRespuesta",method= RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public ResultadoDTO guardarRespuestaPartida(@RequestBody RespuestaPreguntaDTO respuesta){

		respuestaService.guardarRespuestaPartida(respuesta.getPartidaId(), respuesta.getUsuarioId(), respuesta.getPreguntaId(), respuesta.getRespuestaId());
		return new ResultadoDTO("SUCCESS");
	}
	
	/*Asignar el turno a un jugador*/
	
	@RequestMapping(value="/asignarTurno", method= RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public ResultadoDTO jugadorSiguiente(@RequestBody TurnoDTO turno){

		juegoService.jugadorSiguiente(turno.getPartidaId(), turno.getUsuarioId());
		return new ResultadoDTO("SUCCESS");
	}
	
	/*MiTurno: Indica si es nuestro turno de jugar o no*/
	@RequestMapping(value= "/miTurno",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"partidaId", "usuarioId"})
	@ResponseBody
	public Boolean miTurno(@RequestParam (value = "partidaId") Long partidaId, @RequestParam (value = "usuarioId") Long usuarioId){
		Long turnoUsuario = juegoService.miTurno(partidaId);
		
		Boolean turno = false;
		if(turnoUsuario.equals(usuarioId) ){
			turno = true;
		}
		
		return turno;
	}
	
	/*partidaTerminada: Metodo para indicar si la partida es terminada o no*/
	@RequestMapping(value="/partidaTerminada", method= RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Boolean partidaTerminada(@RequestBody IdDTO idPartida){
		
		partidaService.partidaTerminada(idPartida.getId()); 
		
		return false;
		
	}
	
	/*Recuperar una pregunta que el jugador ya no haya contestado.*/
	@RequestMapping(value= "/recuperarUnaPregunta",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"partidaId", "asignaturaId", "dificultadId"})
	@ResponseBody
	public IdDTO recuperarUnaPregunta ( @RequestParam(value = "partidaId") Long partidaId, @RequestParam(value = "asignaturaId") Long asignaturaId,
			  @RequestParam(value = "dificultadId") Long dificultadId){
		
		final String username = SecurityContextHolder.getContext().getAuthentication().getName();
		
		Long usuarioId = usuarioService.recuperarIdUsuario(username);
		
		Long preguntaId = preguntaService.recuperarUnaPregunta(partidaId, asignaturaId, dificultadId, usuarioId);
		IdDTO idDto = new IdDTO();
		idDto.setId(preguntaId);
		
		if (preguntaId != null) {
			partidaService.insertarUnaPregunta(preguntaId, partidaId, usuarioId);
		}
		return idDto;
		
	}
	
	/*RecuperarPuntuacion: recupera la puntuacion de un usuario en la partida*/
	@RequestMapping(value= "/recuperarPuntuacion",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"partidaId", "usuarioId"})
	@ResponseBody
	public Long recuperarPuntuacion(@RequestParam (value = "partidaId") Long partidaId, @RequestParam (value = "usuarioId") Long usuarioId){

		Long puntuacion = partidaService.recuperarPuntuacion(partidaId, usuarioId);
		return puntuacion;
	}
	
	@RequestMapping(value= "/recuperarPuntuacionGlobal",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"partidaId"})
	@ResponseBody
	public List<PuntuacionDTO> recuperarPuntuacionGlobal(@RequestParam (value = "partidaId") Long partidaId){
		
		final List<PuntuacionBean> puntuacion = partidaService.recuperarPuntuacion(partidaId);
		final List<PuntuacionDTO> dtos = new ArrayList<PuntuacionDTO>();
		for (PuntuacionBean bean : puntuacion) {
			PuntuacionDTO dto = new PuntuacionDTO();
			dto.setApodo(bean.getApodo());
			dto.setPuntos(bean.getPuntuacion());
			
			dtos.add(dto);
		}
		
		return dtos;
	}
	
	/*M�todo para dar la puntuacion a cada usuario cuando la partida es de varios jugadores*/
	@RequestMapping(value="/puntuacion", method= RequestMethod.POST,
			produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public ResultadoDTO puntuacion(@RequestBody PuntosDTO puntos){
		
		partidaService.puntuacion(puntos.getPartidaId(), puntos.getUsuarioId(), puntos.getPuntuacionTotal());
	
		return new ResultadoDTO("SUCCESS");
	}
	
	/*Metodo para recuperar si la partida esta acabada o no */
	
	@RequestMapping(value= "/estadoPartida",method= RequestMethod.GET,
			produces = MediaType.APPLICATION_JSON_VALUE, params = {"partidaId"})
	@ResponseBody
	public Boolean RecuperarEstadoPartida(@RequestParam (value = "partidaId") Long partidaId){
		
		Boolean estado = partidaService.recuperarEstadoPartida(partidaId);
			
		return estado;
	}
	
	
}
